home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / demo2.zoo / demo / ex / ex_vadj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-04-24  |  23.8 KB  |  1,090 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *sccsid = "@(#)ex_vadj.c    7.10 (Berkeley) 3/9/87; 1.2 (Bellcore)    87/04/24";
  9. #endif not lint
  10.  
  11. #include "ex.h"
  12. #include "ex_tty.h"
  13. #include "ex_vis.h"
  14.  
  15. /*
  16.  * Routines to deal with management of logical versus physical
  17.  * display, opening and redisplaying lines on the screen, and
  18.  * use of intelligent terminal operations.  Routines to deal with
  19.  * screen cleanup after a change.
  20.  */
  21.  
  22. /*
  23.  * Display a new line at physical line p, returning
  24.  * the depth of the newly displayed line.  We may decide
  25.  * to expand the window on an intelligent terminal if it is
  26.  * less than a full screen by deleting a line above the top of the
  27.  * window before doing an insert line to keep all the good text
  28.  * on the screen in which case the line may actually end up
  29.  * somewhere other than line p.
  30.  */
  31. vopen(tp, p)
  32.     line *tp;
  33.     int p;
  34. {
  35.     register int cnt;
  36.     register struct vlinfo *vp, *vpc;
  37.  
  38. #ifdef ADEBUG
  39.     if (trace != NULL)
  40.         tfixnl(), fprintf(trace, "vopen(%d, %d)\n", lineno(tp), p);
  41. #endif
  42.     if (state != VISUAL) {
  43.         if (vcnt)
  44.             if (hold & HOLDROL)
  45.                 vup1();
  46.             else
  47.                 vclean();
  48.  
  49.         /*
  50.          * Forget all that we once knew.
  51.          */
  52.         vcnt = vcline = 0;
  53.         p = WBOT; LASTLINE = WBOT + 1;
  54.         state = bastate;
  55.         WTOP = basWTOP;
  56.         WLINES = basWLINES;
  57.     }
  58.     vpc = &vlinfo[vcline];
  59.     for (vp = &vlinfo[vcnt]; vp >= vpc; vp--)
  60.         vlcopy(vp[1], vp[0]);
  61.     vcnt++;
  62.     if (Pline == numbline)
  63.         /*
  64.          * Dirtying all the lines is rather inefficient
  65.          * internally, but number mode is used rarely
  66.          * and so its not worth optimizing.
  67.          */
  68.         vdirty(vcline+1, WECHO);
  69.     getline(*tp);
  70.  
  71.     /*
  72.      * If we are opening at the top of the window, can try a window
  73.      * expansion at the top.
  74.      */
  75.     if (state == VISUAL && vcline == 0 && vcnt > 1 && p > ex_ZERO) {
  76.         cnt = p + vdepth() - LINE(1);
  77.         if (cnt > 0) {
  78.             p -= cnt;
  79.             if (p < ex_ZERO)
  80.                 p = ex_ZERO;
  81.             WTOP = p;
  82.             WLINES = WBOT - WTOP + 1;
  83.         }
  84.     }
  85.     vpc->vliny = p, vpc->vdepth = 0, vpc->vflags = 0;
  86.     cnt = vreopen(p, lineno(tp), vcline);
  87.     if (vcline + 1 == vcnt)
  88.         LINE(vcnt) = LINE(vcline) + cnt;
  89. }
  90.  
  91. /*
  92.  * Redisplay logical line l at physical line p with line number lineno.
  93.  */
  94. vreopen(p, lineno, l)
  95.     int p, lineno, l;
  96. {
  97.     register int d;
  98.     register struct vlinfo *vp = &vlinfo[l];
  99.  
  100.     d = vp->vdepth;
  101.     if (d == 0 || (vp->vflags & VDIRT))
  102.         vp->vdepth = d = vdepth();
  103.     vp->vliny = p, vp->vflags &= ~VDIRT;
  104.  
  105.     /*
  106.      * Try to win by making the screen larger rather than inserting
  107.      * a line and driving text off the bottom.
  108.      */
  109.     p = vglitchup(l, 0);
  110.  
  111.     /*
  112.      * BUG:        Should consider using CE here to clear to end of line.
  113.      *        As it stands we always strike over the current text.
  114.      *        Since often the current text is the same as what
  115.      *        we are overstriking with, it tends not to show.
  116.      *        On the other hand if it is different and we end up
  117.      *        spacing out a lot of text, we could have won with
  118.      *        a CE.  This is probably worthwhile at low speed
  119.      *        only however, since clearly computation will be
  120.      *        necessary to determine which way to go.
  121.      */
  122.     vigoto(p, 0);
  123.     pline(lineno);
  124.  
  125.     /*
  126.      * When we are typing part of a line for hardcopy open, don't
  127.      * want to type the '$' marking an end of line if in list mode.
  128.      */
  129.     if (hold & HOLDDOL)
  130.         return (d);
  131.     if (Put_char == listchar)
  132.         ex_putchar('$');
  133.  
  134.     /*
  135.      * Optimization of cursor motion may prevent screen rollup if the
  136.      * line has blanks/tabs at the end unless we force the cursor to appear
  137.      * on the last line segment.
  138.      */
  139.     if (vp->vliny + d - 1 > WBOT)
  140.         vcsync();
  141.  
  142.     /*
  143.      * Switch into hardcopy open mode if we are in one line (adm3)
  144.      * open mode and this line is now too long.  If in hardcopy
  145.      * open mode, then call sethard to move onto the next line
  146.      * with appropriate positioning.
  147.      */
  148.     if (state == ONEOPEN) {
  149.         WCOLS = OCOLUMNS;
  150.         if (vdepth() > 1) {
  151.             WCOLS = TUBECOLS;
  152.             sethard();
  153.         } else
  154.             WCOLS = TUBECOLS;
  155.     } else if (state == HARDOPEN)
  156.         sethard();
  157.  
  158.     /*
  159.      * Unless we filled (completely) the last line we typed on,
  160.      * we have to clear to the end of the line
  161.      * in case stuff is left from before.
  162.      */
  163.     if (vp->vliny + d > destline) {
  164.         if (IN && destcol == WCOLS)
  165.             vigoto(vp->vliny + d - 1, 0);
  166.         vclreol();
  167.     }
  168.     return (d);
  169. }
  170.  
  171. /*
  172.  * Real work for winning growing of window at top
  173.  * when inserting in the middle of a partially full
  174.  * screen on an intelligent terminal.  We have as argument
  175.  * the logical line number to be inserted after, and the offset
  176.  * from that line where the insert will go.
  177.  * We look at the picture of depths and positions, and if we can
  178.  * delete some (blank) lines from the top of the screen so that
  179.  * later inserts will not push stuff off the bottom.
  180.  */
  181. vglitchup(l, o)
  182.     int l, o;
  183. {
  184.     register struct vlinfo *vp = &vlinfo[l];
  185.     register int need;
  186.     register int p = vp->vliny;
  187.     short oldhold, oldheldech;
  188.     bool glitched = 0;
  189.  
  190.      if (l < vcnt - 1) {
  191.         need = p + vp->vdepth - (vp+1)->vliny;
  192.         if (need > 0) {
  193.             if (state == VISUAL && WTOP - ex_ZERO >= need && AL && DL) {
  194.                 glitched++;
  195.                 WTOP -= need;
  196.                 WLINES = WBOT - WTOP + 1;
  197.                 p -= need;
  198.                 if (p + o == WTOP) {
  199.                     vp->vliny = WTOP;
  200.                     return (WTOP + o);
  201.                 }
  202.                 vdellin(WTOP, need, -1);
  203.                 oldheldech = heldech;
  204.                 oldhold = hold;
  205.                 hold |= HOLDECH;
  206.             }
  207.             vinslin((vp+1)->vliny, need, l);
  208.             if (glitched) {
  209.                 hold = oldhold;
  210.                 heldech = oldheldech;
  211.             }
  212.         }
  213.     } else
  214.         vp[1].vliny = vp[0].vliny + vp->vdepth;
  215.     return (p + o);
  216. }
  217.  
  218. /*
  219.  * Insert cnt blank lines before line p,
  220.  * logically and (if supported) physically.
  221.  */
  222. vinslin(p, cnt, l)
  223.     register int p, cnt;
  224.     int l;
  225. {
  226.     register int i;
  227.     bool could = 1;
  228.  
  229. #ifdef ADEBUG
  230.     if (trace)
  231.         tfixnl(), fprintf(trace, "vinslin(%d, %d, %d)\n", p, cnt, l);
  232. #endif
  233.     if (p + cnt > WBOT && CD) {
  234.         /*
  235.          * Really quick -- clear to end of screen.
  236.          */
  237.         cnt = WECHO + 1 - p;
  238.         vgoto(p, 0), vputp(CD, cnt);
  239.         vclrech(1);
  240.         vadjAL(p, cnt);
  241.     } else if (SR && p == WTOP && costSR < costAL) {
  242.         /*
  243.          * Use reverse scroll mode of the terminal, at
  244.          * the top of the window.  Reverse linefeed works
  245.          * too, since we only use it from line WTOP.
  246.          */
  247.         for (i = cnt; i > 0; i--) {
  248.             vgoto(p, 0), vputp(SR, 0);
  249.             if (i > 1 && (hold & HOLDAT) == 0)
  250.                 ex_putchar('@');
  251.             /*
  252.              * If we are at the top of the screen, and the
  253.              * terminal retains display above, then we
  254.              * should try to clear to end of line.
  255.              * Have to use CE since we don't remember what is
  256.              * actually on the line.
  257.              */
  258.             if (CE && (DA || p != 0))
  259.                 vputp(CE, 1);
  260.         }
  261.         vadjAL(p, cnt);
  262.     } else if (AL) {
  263.         /*
  264.          * Use insert line.
  265.          */
  266.         vgoto(p, 0);
  267.         if (AL_PARM && (cnt>1 || *AL==0)) {
  268.             /* insert cnt lines.  Should do @'s too. */
  269.             vputp(tgoto(AL_PARM, p, cnt), WECHO+1-p);
  270.         }
  271.         else if (CS && *AL==0) {
  272.             /* vt100 change scrolling region to fake AL */
  273.             vputp(SC, 1);
  274.             vputp(tgoto(CS, LINES-1,p), 1);
  275.             vputp(RC, 1);    /* CS homes stupid cursor */
  276.             for (i=cnt; i>0; i--)
  277.                 vputp(SR, 1);    /* should do @'s */
  278.             vputp(tgoto(CS, LINES-1,0), 1);
  279.             vputp(RC, 1);    /* Once again put it back */
  280.         }
  281.         else {
  282.             vputp(AL, WECHO + 1 - p);
  283.             for (i = cnt - 1; i > 0; i--) {
  284.                 vgoto(outline+1, 0);
  285.                 vputp(AL, WECHO + 1 - outline);
  286.                 if ((hold & HOLDAT) == 0)
  287.                     ex_putchar('@');
  288.             }
  289.         }
  290.         vadjAL(p, cnt);
  291.     } else
  292.         could = 0;
  293.     vopenup(cnt, could, l);
  294. }
  295.  
  296. /*
  297.  * Logically open up after line l, cnt of them.
  298.  * We need to know if it was done ``physically'' since in this
  299.  * case we accept what the hardware gives us.  If we have to do
  300.  * it ourselves (brute force) we will squish out @ lines in the process
  301.  * if this will save us work.
  302.  */
  303. vopenup(cnt, could, l)
  304.     int cnt;
  305.     bool could;
  306. {
  307.     register struct vlinfo *vc = &vlinfo[l + 1];
  308.     register struct vlinfo *ve = &vlinfo[vcnt];
  309.  
  310. #ifdef ADEBUG
  311.     if (trace)
  312.         tfixnl(), fprintf(trace, "vopenup(%d, %d, %d)\n", cnt, could, l);
  313. #endif
  314.     if (could)
  315.         /*
  316.          * This will push @ lines down the screen,
  317.          * just as the hardware did.  Since the default
  318.          * for intelligent terminals is to never have @
  319.          * lines on the screen, this should never happen,
  320.          * and the code makes no special effort to be nice in this
  321.          * case, e.g. squishing out the @ lines by delete lines
  322.          * before doing append lines.
  323.          */
  324.         for (; vc <= ve; vc++)
  325.             vc->vliny += cnt;
  326.     else {
  327.         /*
  328.          * Will have to clean up brute force eventually,
  329.          * so push the line data around as little as possible.
  330.          */
  331.         vc->vliny += cnt, vc->vflags |= VDIRT;
  332.         while (vc < ve) {
  333.             register int i = vc->vliny + vc->vdepth;
  334.  
  335.             vc++;
  336.             if (i <= vc->vliny)
  337.                 break;
  338.             vc->vliny = i, vc->vflags |= VDIRT;
  339.         }
  340.     }
  341.     vscrap();
  342. }
  343.  
  344. /*
  345.  * Adjust data structure internally to account for insertion of
  346.  * blank lines on the screen.
  347.  */
  348. vadjAL(p, cnt)
  349.     int p, cnt;
  350. {
  351.     char *tlines[TUBELINES];
  352.     register int from, to;
  353.  
  354. #ifdef ADEBUG
  355.     if (trace)
  356.         tfixnl(), fprintf(trace, "vadjal(%d, %d)\n", p, cnt);
  357. #endif
  358.     copy(tlines, vtube, sizeof vtube);    /*SASSIGN*/
  359.     for (from = p, to = p + cnt; to <= WECHO; from++, to++)
  360.         vtube[to] = tlines[from];
  361.     for (to = p; from <= WECHO; from++, to++) {
  362.         vtube[to] = tlines[from];
  363.         vclrbyte(vtube[to], WCOLS);
  364.     }
  365.     /*
  366.      * Have to clear the echo area since its contents aren't
  367.      * necessarily consistent with the rest of the display.
  368.      */
  369.     vclrech(0);
  370. }
  371.  
  372. /*
  373.  * Roll the screen up logically and physically
  374.  * so that line dl is the bottom line on the screen.
  375.  */
  376. vrollup(dl)
  377.     int dl;
  378. {
  379.     register int cnt;
  380.     register int dc = destcol;
  381.  
  382. #ifdef ADEBUG
  383.     if (trace)
  384.         tfixnl(), fprintf(trace, "vrollup(%d)\n", dl);
  385. #endif
  386.     cnt = dl - (splitw ? WECHO : WBOT);
  387.     if (splitw && (state == VISUAL || state == CRTOPEN))
  388.         holdupd = 1;
  389.     vmoveitup(cnt, 1);
  390.     vscroll(cnt);
  391.     destline = dl - cnt, destcol = dc;
  392. }
  393.  
  394. vup1()
  395. {
  396.  
  397.     vrollup(WBOT + 1);
  398. }
  399.  
  400. /*
  401.  * Scroll the screen up cnt lines physically.
  402.  * If doclr is true, do a clear eol if the terminal
  403.  * has standout (to prevent it from scrolling up)
  404.  */
  405. vmoveitup(cnt, doclr)
  406.     register int cnt;
  407.     bool doclr;
  408. {
  409.  
  410.     if (cnt == 0)
  411.         return;
  412. #ifdef ADEBUG
  413.     if (trace)
  414.         tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt);
  415. #endif
  416.     if (doclr && (SO || SE))
  417.         vclrech(0);
  418.     if (SF) {
  419.         destline = WECHO;
  420.         destcol = (NONL ? 0 : outcol % WCOLS);
  421.         fgoto();
  422.         while (cnt > 0)
  423.             vputp(SF, 0), cnt--;
  424.         return;
  425.     }
  426.     destline = WECHO + cnt;
  427.     destcol = (NONL ? 0 : outcol % WCOLS);
  428.     fgoto();
  429.     if (state == ONEOPEN || state == HARDOPEN) {
  430.         outline = destline = 0;
  431.         vclrbyte(vtube[0], WCOLS);
  432.     }
  433. }
  434.  
  435. /*
  436.  * Scroll the screen up cnt lines logically.
  437.  */
  438. vscroll(cnt)
  439.     register int cnt;
  440. {
  441.     register int from, to;
  442.     char *tlines[TUBELINES];
  443.  
  444. #ifdef ADEBUG
  445.     if (trace)
  446.         fprintf(trace, "vscroll(%d)\n", cnt);
  447. #endif
  448.     if (cnt < 0 || cnt > TUBELINES)
  449.         error("Internal error: vscroll");
  450.     if (cnt == 0)
  451.         return;
  452.     copy(tlines, vtube, sizeof vtube);
  453.     for (to = ex_ZERO, from = ex_ZERO + cnt; to <= WECHO - cnt; to++, from++)
  454.         vtube[to] = tlines[from];
  455.     for (from = ex_ZERO; to <= WECHO; to++, from++) {
  456.         vtube[to] = tlines[from];
  457.         vclrbyte(vtube[to], WCOLS);
  458.     }
  459.     for (from = 0; from <= vcnt; from++)
  460.         LINE(from) -= cnt;
  461. }
  462.  
  463. /*
  464.  * Discard logical lines due to physical wandering off the screen.
  465.  */
  466. vscrap()
  467. {
  468.     register int i, j;
  469.  
  470. #ifdef ADEBUG
  471.     if (trace)
  472.         tfixnl(), fprintf(trace, "vscrap\n"), tvliny();
  473. #endif
  474.     if (splitw)
  475.         return;
  476.     if (vcnt && WBOT != WECHO && LINE(0) < WTOP && LINE(0) >= ex_ZERO) {
  477.         WTOP = LINE(0);
  478.         WLINES = WBOT - WTOP + 1;
  479.     }
  480.     for (j = 0; j < vcnt; j++)
  481.         if (LINE(j) >= WTOP) {
  482.             if (j == 0)
  483.                 break;
  484.             /*
  485.              * Discard the first j physical lines off the top.
  486.              */
  487.             vcnt -= j, vcline -= j;
  488.             for (i = 0; i <= vcnt; i++)
  489.                 vlcopy(vlinfo[i], vlinfo[i + j]);
  490.             break;
  491.         }
  492.     /*
  493.      * Discard lines off the bottom.
  494.      */
  495.     if (vcnt) {
  496.         for (j = 0; j <= vcnt; j++)
  497.             if (LINE(j) > WBOT || LINE(j) + DEPTH(j) - 1 > WBOT) {
  498.                 vcnt = j;
  499.                 break;
  500.             }
  501.         LASTLINE = LINE(vcnt-1) + DEPTH(vcnt-1);
  502.     }
  503. #ifdef ADEBUG
  504.     if (trace)
  505.         tvliny();
  506. #endif
  507.     /*
  508.      * May have no lines!
  509.      */
  510. }
  511.  
  512. /*
  513.  * Repaint the screen, with cursor at curs, aftern an arbitrary change.
  514.  * Handle notification on large changes.
  515.  */
  516. vrepaint(curs)
  517.     char *curs;
  518. {
  519.  
  520.     wdot = NOLINE;
  521.     /*
  522.      * In open want to notify first.
  523.      */
  524.     ignore(noteit(0));
  525.     vscrap();
  526.  
  527.     /*
  528.      * Deal with a totally useless display.
  529.      */
  530.     if (vcnt == 0 || vcline < 0 || vcline > vcnt || holdupd && state != VISUAL) {
  531.         register line *odol = dol;
  532.  
  533.         vcnt = 0;
  534.         if (holdupd)
  535.             if (state == VISUAL)
  536.                 ignore(peekkey());
  537.             else
  538.                 vup1();
  539.         holdupd = 0;
  540.         if (odol == zero)
  541.             fixzero();
  542.         vcontext(dot, '.');
  543.         ignore(noteit(1));
  544.         if (noteit(1) == 0 && odol == zero) {
  545.             CATCH
  546.                 error("No lines in buffer");
  547.             ENDCATCH
  548.             linebuf[0] = 0;
  549.             splitw = 0;
  550.         }
  551.         vnline(curs);
  552.         return;
  553.     }
  554.  
  555.     /*
  556.      * Have some useful displayed text; refresh it.
  557.      */
  558.     getDOT();
  559.  
  560.     /*
  561.      * This is for boundary conditions in open mode.
  562.      */
  563.     if (FLAGS(0) & VDIRT)
  564.         vsync(WTOP);
  565.     
  566.     /*
  567.      * If the current line is after the last displayed line
  568.      * or the bottom of the screen, then special effort is needed
  569.      * to get it on the screen.  We first try a redraw at the
  570.      * last line on the screen, hoping it will fill in where @
  571.      * lines are now.  If this doesn't work, then roll it onto
  572.      * the screen.
  573.      */
  574.     if (vcline >= vcnt || LINE(vcline) > WBOT) {
  575.         short oldhold = hold;
  576.         hold |= HOLDAT, vredraw(LASTLINE), hold = oldhold;
  577.         if (vcline >= vcnt) {
  578.             register int i = vcline - vcnt + 1;
  579.  
  580.             dot -= i;
  581.             vcline -= i;
  582.             vroll(i);
  583.         } else
  584.             vsyncCL();
  585.     } else
  586.         vsync(vcline > 0 ? LINE(vcline - 1) : WTOP);
  587.  
  588.     /*
  589.      * Notification on large change for visual
  590.      * has to be done last or we may lose
  591.      * the echo area with redisplay.
  592.      */
  593.     ignore(noteit(1));
  594.  
  595.     /*
  596.      * Finally.  Move the cursor onto the current line.
  597.      */
  598.     vnline(curs);
  599. }
  600.  
  601. /*
  602.  * Fully cleanup the screen, leaving no @ lines except at end when
  603.  * line after last won't completely fit.  The routine vsync is
  604.  * more conservative and much less work on dumb terminals.
  605.  */
  606. vredraw(p)
  607.     register int p;
  608. {
  609.     register int l;
  610.     register line *tp;
  611.     char temp[LBSIZE];
  612.     bool anydl = 0;
  613.     short oldhold = hold;
  614.  
  615. #ifdef ADEBUG
  616.     if (trace)
  617.         tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny();
  618. #endif
  619.     if (holdupd) {
  620.         holdupd = 3;
  621.         return;
  622.     }
  623.     if (state == HARDOPEN || splitw)
  624.         return;
  625.     if (p < 0 /* || p > WECHO */)
  626.         error("Internal error: vredraw");
  627.  
  628.     /*
  629.      * Trim the ragged edges (lines which are off the screen but
  630.      * not yet logically discarded), save the current line, and
  631.      * search for first logical line affected by the redraw.
  632.      */
  633.     vscrap();
  634.     CP(temp, linebuf);
  635.     l = 0;
  636.     tp = dot - vcline;
  637.     if (vcnt == 0)
  638.         LINE(0) = WTOP;
  639.     while (l < vcnt && LINE(l) < p)
  640.         l++, tp++;
  641.  
  642.     /*
  643.      * We hold off echo area clearing during the redraw in deference
  644.      * to a final clear of the echo area at the end if appropriate.
  645.      */
  646.     heldech = 0;
  647.     hold |= HOLDECH;
  648.     for (; l < vcnt && Peek_key != ATTN; l++) {
  649.         if (l == vcline)
  650.             strcLIN(temp);
  651.         else
  652.             getline(*tp);
  653.  
  654.         /*
  655.          * Delete junk between displayed lines.
  656.          */
  657.         if (LINE(l) != LINE(l + 1) && LINE(l) != p) {
  658.             if (anydl == 0 && DB && CD) {
  659.                 hold = oldhold;
  660.                 vclrech(0);
  661.                 anydl = 1;
  662.                 hold |= HOLDECH;
  663.                 heldech = 0;
  664.             }
  665.             vdellin(p, LINE(l) - p, l);
  666.         }
  667.  
  668.         /*
  669.          * If line image is not know to be up to date, then
  670.          * redisplay it;  else just skip onward.
  671.          */
  672.         LINE(l) = p;
  673.         if (FLAGS(l) & VDIRT) {
  674.             DEPTH(l) = vdepth();
  675.             if (l != vcline && p + DEPTH(l) - 1 > WBOT) {
  676.                 vscrap();
  677.                 break;
  678.             }
  679.             FLAGS(l) &= ~VDIRT;
  680.             ignore(vreopen(p, lineno(tp), l));
  681.             p = LINE(l) + DEPTH(l);
  682.         } else
  683.             p += DEPTH(l);
  684.         tp++;
  685.     }
  686.  
  687.     /*
  688.      * That takes care of lines which were already partially displayed.
  689.      * Now try to fill the rest of the screen with text.
  690.      */
  691.     if (state == VISUAL && p <= WBOT) {
  692.         int ovcline = vcline;
  693.  
  694.         vcline = l;
  695.         for (; tp <= dol && Peek_key != ATTN; tp++) {
  696.             getline(*tp);
  697.             if (p + vdepth() - 1 > WBOT)
  698.                 break;
  699.             vopen(tp, p);
  700.             p += DEPTH(vcline);
  701.             vcline++;
  702.         }
  703.         vcline = ovcline;
  704.     }
  705.  
  706.     /*
  707.      * Thats all the text we can get on.
  708.      * Now rest of lines (if any) get either a ~ if they
  709.      * are past end of file, or an @ if the next line won't fit.
  710.      */
  711.     for (; p <= WBOT && Peek_key != ATTN; p++)            
  712.         vclrlin(p, tp);
  713.     strcLIN(temp);
  714.     hold = oldhold;
  715.     if (heldech)
  716.         vclrech(0);
  717. #ifdef ADEBUG
  718.     if (trace)
  719.         tvliny();
  720. #endif
  721. }
  722.  
  723. /*
  724.  * Do the real work in deleting cnt lines starting at line p from
  725.  * the display.  First affected line is line l.
  726.  */
  727. vdellin(p, cnt, l)
  728.     int p, cnt, l;
  729. {
  730.     register int i;
  731.  
  732.     if (cnt == 0)
  733.         return;
  734.     if (DL == NOSTR || cnt < 0) {
  735.         /*
  736.          * Can't do it; just remember that line l is munged.
  737.          */
  738.         FLAGS(l) |= VDIRT;
  739.         return;
  740.     }
  741. #ifdef ADEBUG
  742.     if (trace)
  743.         tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l);
  744. #endif
  745.     /*
  746.      * Send the deletes to the screen and then adjust logical
  747.      * and physical internal data structures.
  748.      */
  749.     vgoto(p, 0);
  750.     if (DL_PARM && (cnt>1 || *DL==0)) {
  751.         vputp(tgoto(DL_PARM, p, cnt), WECHO-p);
  752.     }
  753.     else if (CS && *DL==0) {
  754.         /* vt100: fake DL by changing scrolling region */
  755.         vputp(SC, 1);    /* Save since CS homes stupid cursor */
  756.         vputp(tgoto(CS, LINES-1, p), 1);
  757.         vputp(tgoto(CM, 0, LINES-1), 1);/* Go to lower left corner */
  758.         for (i=0; i<cnt; i++)        /* .. and scroll cnt times */
  759.             putch('\n');        /* should check NL too */
  760.         vputp(tgoto(CS, LINES-1, 0), 1);/* restore scrolling region */
  761.         vputp(RC, 1);            /* put cursor back */
  762.     }
  763.     else {
  764.         for (i = 0; i < cnt; i++)
  765.             vputp(DL, WECHO - p);
  766.     }
  767.     vadjDL(p, cnt);
  768.     vcloseup(l, cnt);
  769. }
  770. /*
  771.  * Adjust internal physical screen image to account for deleted lines.
  772.  */
  773. vadjDL(p, cnt)
  774.     int p, cnt;
  775. {
  776.     char *tlines[TUBELINES];
  777.     register int from, to;
  778.  
  779. #ifdef ADEBUG
  780.     if (trace)
  781.         tfixnl(), fprintf(trace, "vadjDL(%d, %d)\n", p, cnt);
  782. #endif
  783.     /*
  784.      * Would like to use structured assignment but early
  785.      * v7 compiler (released with phototypesetter for v6)
  786.      * can't hack it.
  787.      */
  788.     copy(tlines, vtube, sizeof vtube);    /*SASSIGN*/
  789.     for (from = p + cnt, to = p; from <= WECHO; from++, to++)
  790.         vtube[to] = tlines[from];
  791.     for (from = p; to <= WECHO; from++, to++) {
  792.         vtube[to] = tlines[from];
  793.         vclrbyte(vtube[to], WCOLS);
  794.     }
  795. }
  796. /*
  797.  * Sync the screen, like redraw but more lazy and willing to leave
  798.  * @ lines on the screen.  VsyncCL syncs starting at the current line.
  799.  * In any case, if the redraw option is set then all syncs map to redraws
  800.  * as if vsync didn't exist.
  801.  */
  802. vsyncCL()
  803. {
  804.  
  805.     vsync(LINE(vcline));
  806. }
  807.  
  808. vsync(p)
  809.     register int p;
  810. {
  811.  
  812.     if (value(REDRAW))
  813.         vredraw(p);
  814.     else
  815.         vsync1(p);
  816. }
  817.  
  818. /*
  819.  * The guts of a sync.  Similar to redraw but
  820.  * just less ambitous.
  821.  */
  822. vsync1(p)
  823.     register int p;
  824. {
  825.     register int l;
  826.     char temp[LBSIZE];
  827.     register struct vlinfo *vp = &vlinfo[0];
  828.     short oldhold = hold;
  829.  
  830. #ifdef ADEBUG
  831.     if (trace)
  832.         tfixnl(), fprintf(trace, "vsync1(%d)\n", p), tvliny();
  833. #endif
  834.     if (holdupd) {
  835.         if (holdupd < 3)
  836.             holdupd = 2;
  837.         return;
  838.     }
  839.     if (state == HARDOPEN || splitw)
  840.         return;
  841.     vscrap();
  842.     CP(temp, linebuf);
  843.     if (vcnt == 0)
  844.         LINE(0) = WTOP;
  845.     l = 0;
  846.     while (l < vcnt && vp->vliny < p)
  847.         l++, vp++;
  848.     heldech = 0;
  849.     hold |= HOLDECH;
  850.     while (p <= WBOT && Peek_key != ATTN) {
  851.         /*
  852.          * Want to put a line here if not in visual and first line
  853.          * or if there are lies left and this line starts before
  854.          * the current line, or if this line is piled under the
  855.          * next line (vreplace does this and we undo it).
  856.          */
  857.         if (l == 0 && state != VISUAL ||
  858.             (l < vcnt && (vp->vliny <= p || vp[0].vliny == vp[1].vliny))) {
  859.             if (l == 0 || vp->vliny < p || (vp->vflags & VDIRT)) {
  860.                 if (l == vcline)
  861.                     strcLIN(temp);
  862.                 else
  863.                     getline(dot[l - vcline]);
  864.                 /*
  865.                  * Be careful that a long line doesn't cause the
  866.                  * screen to shoot up.
  867.                  */
  868.                 if (l != vcline && (vp->vflags & VDIRT)) {
  869.                     vp->vdepth = vdepth();
  870.                     vp->vflags &= ~VDIRT;
  871.                     if (p + vp->vdepth - 1 > WBOT)
  872.                         break;
  873.                 }
  874.                 ignore(vreopen(p, lineDOT() + (l - vcline), l));
  875.             }
  876.             p = vp->vliny + vp->vdepth;
  877.             vp++;
  878.             l++;
  879.         } else
  880.             /*
  881.              * A physical line between logical lines,
  882.              * so we settle for an @ at the beginning.
  883.              */
  884.             vclrlin(p, dot + (l - vcline)), p++;
  885.     }
  886.     strcLIN(temp);
  887.     hold = oldhold;
  888.     if (heldech)
  889.         vclrech(0);
  890. }
  891.  
  892. /*
  893.  * Subtract (logically) cnt physical lines from the 
  894.  * displayed position of lines starting with line l.
  895.  */
  896. vcloseup(l, cnt)
  897.     int l;
  898.     register int cnt;
  899. {
  900.     register int i;
  901.  
  902. #ifdef ADEBUG
  903.     if (trace)
  904.         tfixnl(), fprintf(trace, "vcloseup(%d, %d)\n", l, cnt);
  905. #endif
  906.     for (i = l + 1; i <= vcnt; i++)
  907.         LINE(i) -= cnt;
  908. }
  909.  
  910. /*
  911.  * Workhorse for rearranging line descriptors on changes.
  912.  * The idea here is that, starting with line l, cnt lines
  913.  * have been replaced with newcnt lines.  All of these may
  914.  * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0,
  915.  * since we may be called from an undo after the screen has
  916.  * moved a lot.  Thus we have to be careful.
  917.  *
  918.  * Many boundary conditions here.
  919.  */
  920. vreplace(l, cnt, newcnt)
  921.     int l, cnt, newcnt;
  922. {
  923.     register int from, to, i;
  924.     bool savenote = 0;
  925.  
  926. #ifdef ADEBUG
  927.     if (trace) {
  928.         tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt);
  929.         tvliny();
  930.     }
  931. #endif
  932.     if (l >= vcnt)
  933.         return;
  934.     if (l < 0) {
  935.         if (l + cnt < 0) {
  936.             /*
  937.              * Nothing on the screen is relevant.
  938.              * Settle for redrawing from scratch (later).
  939.              */
  940.             vcnt = 0;
  941.             return;
  942.         }
  943.         /*
  944.          * Normalize l to top of screen; the add is
  945.          * really a subtract from cnt since l is negative.
  946.          */
  947.         cnt += l;
  948.         l = 0;
  949.  
  950.         /*
  951.          * Unseen lines were affect so notify (later).
  952.          */
  953.         savenote++;
  954.     }
  955.  
  956.     /*
  957.      * These shouldn't happen
  958.      * but would cause great havoc.
  959.      */
  960.     if (cnt < 0)
  961.         cnt = 0;
  962.     if (newcnt < 0)
  963.         newcnt = 0;
  964.  
  965.     /*
  966.      * Surely worthy of note if more than report
  967.      * lines were changed.
  968.      */
  969.     if (cnt > value(REPORT) || newcnt > value(REPORT))
  970.         savenote++;
  971.  
  972.     /*
  973.      * Same number of lines affeted as on screen, and we
  974.      * can insert and delete lines.  Thus we just type
  975.      * over them, since otherwise we will push them
  976.      * slowly off the screen, a clear lose.
  977.      */
  978.     if (cnt == newcnt || vcnt - l == newcnt && AL && DL) {
  979.         if (cnt > 1 && l + cnt > vcnt)
  980.             savenote++;
  981.         vdirty(l, newcnt);
  982.     } else {
  983.         /*
  984.          * Lines are going away, squish them out.
  985.          */
  986.         if (cnt > 0) {
  987.             /*
  988.              * If non-displayed lines went away,
  989.              * always notify.
  990.              */
  991.             if (cnt > 1 && l + cnt > vcnt)
  992.                 savenote++;
  993.             if (l + cnt >= vcnt)
  994.                 cnt = vcnt - l;
  995.             else
  996.                 for (from = l + cnt, to = l; from <= vcnt; to++, from++)
  997.                     vlcopy(vlinfo[to], vlinfo[from]);
  998.             vcnt -= cnt;
  999.         }
  1000.         /*
  1001.          * Open up space for new lines appearing.
  1002.          * All new lines are piled in the same place,
  1003.          * and will be unpiled by vredraw/vsync, which
  1004.          * inserts lines in front as it unpiles.
  1005.          */
  1006.         if (newcnt > 0) {
  1007.             /*
  1008.              * Newlines are appearing which may not show,
  1009.              * so notify (this is only approximately correct
  1010.              * when long lines are present).
  1011.              */
  1012.             if (newcnt > 1 && l + newcnt > vcnt + 1)
  1013.                 savenote++;
  1014.  
  1015.             /*
  1016.              * If there will be more lines than fit, then
  1017.              * just throw way the rest of the stuff on the screen.
  1018.              */
  1019.             if (l + newcnt > WBOT && AL && DL) {
  1020.                 vcnt = l;
  1021.                 goto skip;
  1022.             }
  1023.             from = vcnt, to = vcnt + newcnt;
  1024.             i = TUBELINES - to;
  1025.             if (i < 0)
  1026.                 from += i, to += i;
  1027.             vcnt = to;
  1028.             for (; from >= l; from--, to--)
  1029.                 vlcopy(vlinfo[to], vlinfo[from]);
  1030.             for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) {
  1031.                 LINE(to) = LINE(from);
  1032.                 DEPTH(to) = 0;
  1033.                 FLAGS(to) = VDIRT;
  1034.             }
  1035.         }
  1036.     }
  1037. skip:
  1038.     if (Pline == numbline && cnt != newcnt)
  1039.         /*
  1040.          * When lines positions are shifted, the numbers
  1041.          * will be wrong.
  1042.          */
  1043.         vdirty(l, WECHO);
  1044.     if (!savenote)
  1045.         notecnt = 0;
  1046. #ifdef ADEBUG
  1047.     if (trace)
  1048.         tvliny();
  1049. #endif
  1050. }
  1051.  
  1052. /*
  1053.  * Start harcopy open.
  1054.  * Print an image of the line to the left of the cursor
  1055.  * under the full print of the line and position the cursor.
  1056.  * If we are in a scroll ^D within hardcopy open then all this
  1057.  * is suppressed.
  1058.  */
  1059. sethard()
  1060. {
  1061.  
  1062.     if (state == VISUAL)
  1063.         return;
  1064.     rubble = 0;
  1065.     state = HARDOPEN;
  1066.     if (hold & HOLDROL)
  1067.         return;
  1068.     vup1();
  1069.     LINE(0) = WBOT;
  1070.     if (Pline == numbline)
  1071.         vgoto(WBOT, 0), ex_printf("%6d  ", lineDOT());
  1072. }
  1073.  
  1074. /*
  1075.  * Mark the lines starting at base for i lines
  1076.  * as dirty so that they will be checked for correct
  1077.  * display at next sync/redraw.
  1078.  */
  1079. vdirty(base, i)
  1080.     register int base, i;
  1081. {
  1082.     register int l;
  1083.     
  1084.     for (l = base; l < vcnt; l++) {
  1085.         if (--i < 0)
  1086.             return;
  1087.         FLAGS(l) |= VDIRT;
  1088.     }
  1089. }
  1090.